﻿using System;
using System.Reflection;
using Wisdom.Core;

namespace Wisdom.Core
{
    /// <summary>
    /// 描述：拦截配置器
    /// </summary>
    public interface IInterceptionConfigurator : IConfigSourceConfigurator { }

    /// <summary>
    /// 拦截配置器
    /// </summary>
    public class InterceptionConfigurator : ConfigSourceConfigurator, IInterceptionConfigurator
    {
        #region Private Fields
        private readonly Type interceptorType;
        private readonly Type contractType;
        private readonly MethodInfo interceptMethod;
        #endregion

        #region Ctor
        /// <summary>
        /// 实始化一个类<c>InterceptionConfigurator</c> 类实例.
        /// </summary>
        /// <param name="context">配置上下文.</param>
        /// <param name="interceptorType">被注册的拦截类型.</param>
        /// <param name="contractType">被拦截类型.</param>
        /// <param name="interceptMethod"> <see cref="MethodInfo"/>需要被拦截的实例 .</param>
        public InterceptionConfigurator(IConfigSourceConfigurator context, Type interceptorType, Type contractType, MethodInfo interceptMethod)
            : base(context)
        {
            this.interceptorType = interceptorType;
            this.contractType = contractType;
            this.interceptMethod = interceptMethod;
        }
        /// <summary>
        /// 初始化 <c>InterceptionConfigurator</c> 类.
        /// </summary>
        /// <param name="context">配置上下文.</param>
        /// <param name="interceptorType">被注册的拦截类型.</param>
        /// <param name="contractType">被拦截类型.</param>
        /// <param name="interceptMethod">被拦截的名称 .</param>
        public InterceptionConfigurator(IConfigSourceConfigurator context, Type interceptorType, Type contractType, string interceptMethod)
            : base(context)
        {
            this.interceptorType = interceptorType;
            this.contractType = contractType;
            var method = contractType.GetMethod(interceptMethod, BindingFlags.Public | BindingFlags.Instance);
            if (method != null)
                this.interceptMethod = method;
            else
                throw new ConfigException("The method {0} requested doesn't exist in type {1}.", interceptMethod, contractType);
        }
        #endregion

        #region Protected Methods
        /// <summary>
        /// Configures the container.
        /// </summary>
        /// <param name="container">The configuration container.</param>
        /// <returns>The configured container.</returns>
        protected override CodeConfigSource DoConfigure(CodeConfigSource container)
        {
            var name = this.interceptorType.FullName;
            container.AddInterceptor(name, this.interceptorType);
            container.AddInterceptorRef(this.contractType, this.interceptMethod, name);
            return container;
        }
        #endregion
    }
}
